<?php

namespace app\services;

use app\traits\Page;
use plugin\admin\app\model\Music;
use plugin\admin\app\model\MusicalInstrument;
use plugin\admin\app\model\MusicMenu;
use plugin\admin\app\model\MusicMenuRelation;
use support\Db;
use Webman\Event\Event;
use Webman\RedisQueue\Redis;

class MusicService
{
    /**
     * 添加乐谱
     *
     * @param $data
     * @return int
     */
    public static function addMusic($data)
    {
        if (!empty($data['pdf'])) {
            $type = Music::TYPE_PDF;
        } else {
            $type = Music::TYPE_IMAGES;
        }

        $sort = Music::where('user_id', get_user_id())->max('sort') + 1;

        $insertData = [
            'user_id' => get_user_id(),
            'name' => $data['name'],
            'author' => $data['author'],
            'thumb' => $data['thumb'],
            'desc' => $data['desc'] ?? '',
            'type' => $type,
            'created_time' => date('Y-m-d H:i:s'),
            'sort' => $sort
        ];

        if ($type == Music::TYPE_IMAGES) {
            $insertData['images'] = json_encode($data['images'], JSON_UNESCAPED_UNICODE);
        }

        if ($type == Music::TYPE_PDF) {
            $insertData['pdf'] = $data['pdf'];
        }

        $musicId = Music::insertGetId($insertData);

        if ($type == Music::TYPE_IMAGES) {
            Redis::send('generate-pdf', [
                'id' => $musicId,
                'images' => $data['images']
            ]);
        }

        return $musicId;
    }

    /**
     * 把图片转成pdf
     *
     * @param $images
     * @return void
     */
    public static function covertImagesToPDF($id, $images)
    {
        if (count($images) == 0) {
            return;
        }

        $relativePath = '/userUpload';
        $folder = public_path() . $relativePath;

        $commandList[] = 'convert';

        foreach ($images as $image) {
            $image = str_replace(full_url(''), public_path(), $image);

            echo $image;
            $commandList[] = $image;
        }

        $commandList[] = '-alpha';
        $commandList[] = 'remove';
        $commandList[] = $folder . '/' . $id . '.pdf';

        exec(join(' ', $commandList));

        Music::where('id', $id)->update(['pdf' => full_url($relativePath . '/' . $id . '.pdf')]);
    }

    /**
     *
     *
     * @param $id
     * @param $data
     * @return void
     * @throws \Exception
     */
    public static function updateMusic($id, $data)
    {
        if (self::ifMusicInvalid($id)) {
            throw new \Exception('不存在的乐谱');
        }

        if (!empty($data['pdf'])) {
            $type = Music::TYPE_PDF;
        } else {
            $type = Music::TYPE_IMAGES;
        }

        $updateData = [
            'user_id' => get_user_id(),
            'name' => $data['name'],
            'author' => $data['author'],
            'thumb' => $data['thumb'],
            'desc' => $data['desc'] ?? '',
            'type' => $type,
            'created_time' => date('Y-m-d H:i:s')
        ];

        if ($type == Music::TYPE_IMAGES) {
            $updateData['images'] = json_encode($data['images'], JSON_UNESCAPED_UNICODE);
            Redis::send('generate-pdf', [
                'id' => $id,
                'images' => $data['images']
            ]);
        }

        if ($type == Music::TYPE_PDF) {
            $updateData['pdf'] = $data['pdf'];
        }

        Music::where('id', $id)->update($updateData);

    }

    /**
     * 是否有效乐谱
     *
     * @param $musicId
     * @return bool
     */
    public static function ifMusicInvalid($musicId)
    {
        return Music::where('user_id', get_user_id())->where('id', $musicId)->count() == 0;
    }

    /**
     * 是否有效谱单
     *
     * @param $menuId
     * @return bool
     */
    public static function ifMenuInvalid($menuId)
    {
        return MusicMenu::where('user_id', get_user_id())->where('id', $menuId)->count() == 0;
    }

    /**
     * 添加乐谱到谱单
     *
     * @param $musicId
     * @param $menuId
     * @return int
     * @throws \Exception
     */
    public static function addMusicToMenu($musicId, $menuId)
    {
        if (self::ifMusicInvalid($musicId)) {
            throw new \Exception('不存在的乐谱');
        }

        if (self::ifMenuInvalid($menuId)) {
            throw new \Exception('不存在的谱单');
        }

        if (MusicMenuRelation::where('music_id', $musicId)->where('menu_id', $menuId)->count() > 0) {
            throw new \Exception('该乐谱已存在，请勿重复添加');
        }

        MusicMenu::where('id', $menuId)->increment('music_count');

        return MusicMenuRelation::insertGetId([
            'music_id' => $musicId,
            'menu_id' => $menuId
        ]);
    }

    /**
     * 从谱单中移除乐谱
     *
     * @param $musicId
     * @param $menuId
     * @return mixed
     * @throws \Exception
     */
    public static function removeMusicFromMenu($musicId, $menuId)
    {
        if (self::ifMusicInvalid($musicId)) {
            throw new \Exception('不存在的乐谱');
        }

        if (self::ifMenuInvalid($menuId)) {
            throw new \Exception('不存在的谱单');
        }

        MusicMenu::where('id', $menuId)->decrement('music_count');

        return MusicMenuRelation::where('music_id', $musicId)->where('menu_id', $menuId)->delete();
    }

    /**
     * 删除乐谱
     *
     * @param $musicId
     * @return void
     * @throws \Exception
     */
    public static function deleteMusic($musicId)
    {
        if (self::ifMusicInvalid($musicId)) {
            throw new \Exception('不存在的乐谱');
        }

        $relation = MusicMenuRelation::where('music_id', $musicId)->get()->toArray();
        $menuIds = array_column($relation, 'menu_id');
        $relationIds = array_column($relation, 'id');

        if (count($menuIds) > 0) {
            MusicMenu::whereIn('id', $menuIds)->decrement('music_count');
        }

        MusicMenuRelation::whereIn('id', $relationIds)->delete();
        Music::where('id', $musicId)->delete();
    }

    public static function showMenu($menuId)
    {
        $res = MusicMenu::find($menuId);

        return $res;
    }

    /**
     * 乐谱详情
     *
     * @param $musicId
     * @return array
     * @throws \Exception
     */
    public static function showMusic($musicId)
    {
        if (self::ifMusicInvalid($musicId)) {
            throw new \Exception('不存在的乐谱');
        }

        $music = Music::find($musicId)->toArray();

        $music['images'] = json_decode($music['images'], true);

        return $music;
    }

    /**
     * 乐谱所属谱单列表
     *
     * @param $musicId
     * @return array
     * @throws \Exception
     */
    public static function showMusicMenus($musicId)
    {
        if (self::ifMusicInvalid($musicId)) {
            throw new \Exception('不存在的乐谱');
        }

        $relation = MusicMenuRelation::where('music_id', $musicId)->get()->toArray();
        $menuIds = array_column($relation, 'menu_id');

        return MusicMenu::select(['id', 'name', 'thumb', 'desc', 'music_count'])->whereIn('id', $menuIds)->get()->toArray();
    }

    /**
     * 导出pdf
     *
     * @param $musicId
     * @return mixed
     */
    public static function exportToPdf($musicId)
    {
        $menu = Music::where('id', $musicId)->first();

        return $menu['pdf'];
    }

    /**
     * 获取所有乐器
     *
     * @return array
     */
    public static function getMusicalInstruments()
    {
        return MusicalInstrument::all()->toArray();
    }

    /**
     * 添加谱单
     *
     * @param $data
     * @return int
     */
    public static function addMusicMenu($data)
    {
        return MusicMenu::insertGetId([
            'user_id' => get_user_id(),
            'name' => $data['name'],
            'desc' => $data['desc'],
            'thumb' => $data['thumb'],
            'music_count' => 0
        ]);
    }

    /**
     * 修改谱单
     *
     * @param $id
     * @param $data
     * @return void
     * @throws \Exception
     */
    public static function updateMusicMenu($id, $data)
    {
        if (self::ifMenuInvalid($id)) {
            throw new \Exception('不存在的谱单');
        }

        $updateData = [
            'name' => $data['name'],
            'desc' => $data['desc'],
            'thumb' => $data['thumb']
        ];

        MusicMenu::where('id', $id)->update($updateData);
    }

    /**
     * 删除谱单
     *
     * @param $id
     * @return void
     * @throws \Exception
     */
    public static function deleteMusicMenu($id)
    {
        if (self::ifMenuInvalid($id)) {
            throw new \Exception('不存在的谱单');
        }

        MusicMenuRelation::where('menu_id', $id)->delete();
        MusicMenu::where('id', $id)->delete();
    }

    /**
     * 乐谱列表
     *
     * @param $page
     * @param $length
     * @param $keyword
     * @return array
     */
    public static function musics($page, $length = 10, $keyword = '')
    {
        $offset = ($page - 1) * $length;

        $query = Music::select(['id', 'thumb', 'name', 'author', 'desc'])->where('user_id', get_user_id());

        if (!empty($keyword)) {
            $query->where('name', 'like', "%{$keyword}%")->orWhere('author', 'like', "%{$keyword}%");
        }

        $totalCount = (clone $query)->count();
        $list = $query->offset($offset)->limit($length)->orderByDesc('sort')->get()->toArray();

        if ($keyword && get_user_id()) {
            Event::dispatch('music.search', $keyword);
        }

        return Page::wrap($totalCount, $page, $length, $list);
    }

    public static function sortUp($id)
    {
        $music = Music::find($id);
        $sort = $music->sort;
        $prev = Music::where('user_id', get_user_id())->where('sort', '>', $sort)->orderBy('sort')->first();

        if ($prev) {
            $music->sort = $prev->sort;
            $prev->sort = $sort;
            $music->save();
            $prev->save();
        } else {
            $music->sort++;
            $music->save();
        }
    }

    public static function sortDown($id)
    {
        $music = Music::find($id);
        $sort = $music->sort;

        $next = Music::where('user_id', get_user_id())->where('sort', '<', $sort)->orderByDesc('sort')->first();

        if ($next) {
            $music->sort = $next->sort;
            $next->sort = $sort;
            $music->save();
            $next->save();
        } else {
            $music->sort--;
            $music->save();
        }
    }

    /**
     * 谱单列表
     *
     * @param $page
     * @param $length
     * @param $keyword
     * @return array
     */
    public static function musicMenus($page, $length = 10, $keyword = '')
    {
        $offset = ($page - 1) * $length;

        $query = Db::table('wa_music_menus', 'mm')
                    ->select(['mm.id', 'mm.thumb', 'mm.name', 'mm.desc', 'mm.music_count'])
                    ->join(Db::raw('wa_music_menu_relations as mmr'), 'mmr.menu_id', '=', 'mm.id', 'left')
                    ->join(Db::raw('wa_musics as m'), 'mmr.music_id', '=', 'm.id', 'left')
                    ->where('mm.user_id', get_user_id());

        if (!empty($keyword)) {
            $query->where('mm.name', 'like', "%{$keyword}%")
                ->orWhere('m.name', 'like', "%{$keyword}%")
                ->orWhere('m.author', 'like', "%{$keyword}%");
        }

        $query = $query->groupBy('mm.id');

        $totalCount = (clone $query)->count();
        $list = $query->offset($offset)->limit($length)->get()->toArray();

        if ($keyword && get_user_id()) {
            Event::dispatch('music-menu.search', $keyword);
        }

        return Page::wrap($totalCount, $page, $length, $list);
    }

    /**
     * 谱单的乐谱列表
     *
     * @param $menuId
     * @param $page
     * @param $length
     * @param $keyword
     * @return array
     */
    public static function musicsFromMenu($menuId, $page, $length, $keyword = '')
    {
        $offset = ($page - 1) * $length;

        $query = Db::table('wa_musics', 'm')
            ->select(['m.id', 'm.name', 'm.thumb', 'm.desc', 'm.author'])
            ->join(Db::raw('wa_music_menu_relations as mmr'), 'mmr.music_id', '=', 'm.id', 'left')
            ->where('m.user_id', get_user_id())
            ->where('mmr.menu_id', $menuId);

        if (!empty($keyword)) {
            $query->orWhere('m.name', 'like', "%{$keyword}%")
                ->orWhere('m.author', 'like', "%{$keyword}%");
        }

        $totalCount = (clone $query)->count();
        $list = $query->offset($offset)->limit($length)->get()->toArray();

        return Page::wrap($totalCount, $page, $length, $list);
    }
}